#pragma once

//对网络地址与主机ip port 做封装
#include<iostream>
#include<string>
#include<string.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<arpa/inet.h>
#include<netinet/in.h>

class InetAddr
{
private:
    void Net2Host()
    {
        //注意网络转主机
        _port = ntohs(_addr.sin_port);
        // _ip = inet_ntoa(_addr.sin_addr);//inet_ntoa 的缓冲区位于静态区，如果多个同时使用inet_ntoa ，线程不安全，更推荐使用inet_ntop
        char inbuffer[64];
        inet_ntop(AF_INET , &_addr.sin_addr.s_addr , inbuffer , sizeof(inbuffer));
        _ip = inbuffer;
    }
    void Host2Net()
    {
        //需要注意主机转网络的问题，同样 inet_addr 也不是线程安全的，推荐使用inet_pton
        _addr.sin_family = AF_INET;
        _addr.sin_port = htons(_port);
        inet_pton(AF_INET , _ip.c_str(), &(_addr.sin_addr.s_addr));
    }
public:
//两种构造
    InetAddr(struct sockaddr_in& addr):_addr(addr)
    {
        //网络地址转主机
        Net2Host();
    }
    InetAddr(uint16_t port , std::string ip = "0.0.0.0")
    :_port(port)
    ,_ip(ip)
    {
        //主机转网络
        Host2Net();
    }
    //默认构造
    InetAddr()
    {}
    void Init(struct sockaddr_in peer)
    {
        _addr = peer;
        Net2Host();
    }
    //一些Get函数
    std::string Ip()
    {
        return _ip;
    }
    uint16_t Port()
    {
        return _port;
    }
    struct sockaddr* Addr()
    {
        return (struct sockaddr*)&_addr;
    }
    socklen_t Length()
    {
        return sizeof(_addr);
    }

    //方便debug
    std::string ToString()
    {
        return _ip + '-' + std::to_string(_port);
    }

    //重载==
    bool operator==(InetAddr& addr)
    {
        return _ip==addr.Ip() && _port==addr.Port();
    }
    ~InetAddr()
    {}
private:
    struct sockaddr_in _addr;
    uint16_t _port;
    std::string _ip;
};